home *** CD-ROM | disk | FTP | other *** search
- ; -*- Mode: Scheme; Syntax: Scheme; Package: Scheme; -*-
- ; File record.scm / Copyright (c) 1989 Jonathan Rees / See file COPYING
-
- ;;;; Record package for Pseudoscheme
-
- (lisp:defstruct (record-type-descriptor (:constructor make-rtd)
- (:print-function print-rtd)
- (:conc-name "RTD-"))
- identification
- unique-id
- field-names
- constructor-function
- predicate-function
- accessor-functions)
-
- (define *record-type-unique-id* 0)
-
- (define package-for-record-functions
- (lisp:make-package
- (lisp:if (lisp:find-package ".RECORD")
- (let loop ((n 0))
- (let ((name (string-append ".RECORD-" (number->string n))))
- (lisp:if (lisp:find-package name)
- (loop (+ n 1))
- name)))
- ".RECORD")
- :use '()))
-
- (define (really-make-record-type type-id field-names)
- (let* ((conc
- (lambda things
- (lisp:intern
- (apply string-append
- (map (lambda (thing)
- (cond ((string? thing) thing)
- ((number? thing)
- (number->string thing))
- ((symbol? thing)
- (lisp:symbol-name thing))
- (else "?")))
- things))
- package-for-record-functions)))
- (id-symbol
- (conc type-id "#" *record-type-unique-id*))
- (constructor-function
- (conc 'make- id-symbol))
- (predicate-function
- (conc id-symbol '?))
- (accessor-functions
- (map (lambda (f)
- (conc id-symbol '- f))
- field-names))
- (rtd (make-rtd :identification type-id
- :unique-id *record-type-unique-id*
- :field-names field-names
- :constructor-function constructor-function
- :predicate-function predicate-function
- :accessor-functions accessor-functions)))
- (lisp:setf (lisp:get id-symbol 'rtd) rtd)
- (let ((lisp:*package* package-for-record-functions))
- ;; Careful -- :CONC-NAME NIL doesn't mean defstruct won't try to
- ;; intern new symbols in current package!
- (lisp:eval `(lisp:defstruct (,id-symbol
- (:constructor ,constructor-function ())
- (:print-function ,(lisp:quote print-record))
- (:predicate ,predicate-function)
- (:copier lisp:nil)
- (:conc-name lisp:nil))
- ,@accessor-functions)))
- (set! *record-type-unique-id* (+ *record-type-unique-id* 1))
- rtd))
-
- (define (record-constructor rtd . init-names-option)
- (let ((cfun (rtd-constructor-function rtd))
- (funs (map (lambda (name)
- (rtd-accessor-function rtd name))
- (if (null? init-names-option)
- (rtd-field-names rtd)
- (car init-names-option)))))
- (lisp:unless (lisp:compiled-function-p (lisp:symbol-function cfun))
- (lisp:compile cfun))
- (lisp:compile 'lisp:nil
- `(lisp:lambda ,funs
- (lisp:let ((the-record (,cfun)))
- ,@(map (lambda (fun)
- `(lisp:setf (,fun the-record)
- ,fun))
- funs)
- the-record)))))
-
- (define (record-predicate rtd)
- (let ((fun (rtd-predicate-function rtd)))
- ; (lisp:unless (lisp:compiled-function-p (lisp:symbol-function fun))
- ; (lisp:compile fun))
- ; (lisp:symbol-function fun)
- (lisp:compile 'lisp:nil
- `(lisp:lambda (x)
- (schi:true? (,fun x))))))
-
- (define (record-accessor rtd name)
- (let ((fun (rtd-accessor-function rtd name)))
- (lisp:unless (lisp:compiled-function-p (lisp:symbol-function fun))
- (lisp:compile fun))
- (lisp:symbol-function fun)))
-
- (define (record-modifier rtd name)
- (let ((fun (rtd-accessor-function rtd name)))
- (lisp:compile 'lisp:nil `(lisp:lambda (x y)
- (lisp:setf (,fun x) y)))))
-
- (define (rtd-accessor-function rtd name)
- (let loop ((l (rtd-field-names rtd))
- (a (rtd-accessor-functions rtd)))
- (if (null? l)
- (lisp:error "~S is not a field name for ~S records"
- name
- (rtd-identification rtd))
- (if (eq? name (car l))
- (car a)
- (loop (cdr l) (cdr a))))))
-
- ; make-record-type:
-
- (define record-type-table (lisp:make-hash-table :test 'lisp:equal))
-
- (define (make-record-type type-id field-names)
- (let* ((key (cons type-id field-names))
- (existing (lisp:gethash key record-type-table)))
- (if (and (not (eq? existing 'lisp:nil))
- (begin (lisp:format lisp:*query-io*
- "~&Existing ~S has fields ~S.~%"
- existing
- field-names)
- (not (eq?
- (lisp:y-or-n-p
- "Use that descriptor (instead of creating a new one)? ")
- 'lisp:nil))))
- existing
- (let ((new (really-make-record-type type-id field-names)))
- (lisp:setf (lisp:gethash key record-type-table) new)
- new))))
-
- (define (record-type record)
- (lisp:get (lisp:type-of record) 'rtd))
-
- ; Printing
-
- (define (print-rtd rtd stream escape?)
- escape? ;ignored
- (lisp:format stream
- "#{Record-type-descriptor ~S.~S}"
- (rtd-identification rtd)
- (rtd-unique-id rtd)))
-
- (define (print-record record stream escape?)
- escape? ;ignored
- (let ((d (disclose-record record)))
- (display "#{")
- (display (if (symbol? (car d))
- (lisp:string-capitalize (symbol->string (car d)))
- (car d))
- stream)
- (for-each (lambda (x)
- (write-char #\space stream)
- (write x stream))
- (cdr d))
- (display "}")))
-
- (define record-disclosers (lisp:make-hash-table))
-
- (define (disclose-record record)
- ((lisp:gethash (record-type record)
- record-disclosers
- default-record-discloser)
- record))
-
- (define (default-record-discloser record)
- (list (rtd-identification (record-type record))))
-
- (define (define-record-discloser rtd proc)
- (lisp:setf (lisp:gethash rtd record-disclosers) proc))
-